const log = require('./log');
const config = require(`../config/${ process.env.ENV }.json`);
const { v4: uuid } = require('uuid');
const { Schema, connect, connection, model, SchemaType, set } = require('mongoose');

set('useCreateIndex', true);
class RegExpType extends SchemaType {
  constructor(key, options) {
    super(key, options);
  }
  cast(value) {
    if (Object.prototype.toString.call(value) !== '[object RegExp]') {
      throw new SchemaType.CastError('RegExp', value + ' is not a RegExp');
    }
    return value;
  }
}

RegExpType.instance = 'RegExpType';
Schema.Types.RegExpType = RegExpType;

const kvSchema = new Schema({
  _id: { type: String, default: uuid },
  checkerId: String,
  key: String,
  parentKey: String,
  value: String,
  describe: String,
  dc: String,
  createIndex: Number,
  modifyIndex: Number,
  lockIndex: Number,
  flags: Number,
  updateUser: String,
  updateTime: String,
  type: String,
}, { versionKey: false });

kvSchema.index({ dc: 1, parentKey: 1, key: 1 });

/** @type { import('mongoose').Model<import('../typings/mongo').Kv, {}>} */
exports.kvModel = model('kv', kvSchema, 'kv');

const historySchema = new Schema({
  _id: { type: String, default: uuid },
  kvId: { type: String, require: true },
  updateUser: String,
  updateTime: String,
  action: String,
  newValue: String,
  oldValue: String,
  modifyIndex: Number,
  success: Boolean,
  errorReson: String,
}, { versionKey: false });

historySchema.index({ kvId: 1 });

/** @type { import('mongoose').Model<import('../typings/mongo').History, {}>} */
exports.historyModel = model('hisotry', historySchema, 'history');

const dcSchema = new Schema({
  _id: { type: String, default: uuid },
  name: String,
}, { versionKey: false });

/** @type { import('mongoose').Model<import('../typings/mongo').Dc, {}>} */
exports.dcModel = model('dc', dcSchema, 'dc');

const validateSchema = new Schema({
  _id: { type: String, default: uuid },
  type: String,
  expression: String,
  regexp: RegExpType,
  script: String,
  json: String,
  name:String,
  describe:String,
}, { versionKey: false });

/** @type { import('mongoose').Model<import('../typings/mongo').Validate, {}>} */
exports.validateModel = model('validate', validateSchema, 'validate');

const checkerSchema = new Schema({
  _id: { type: String, default: uuid },
  validateIdList: [String],
  describe: String,
  name: String,
  updateTime: String,
}, { versionKey: false });

/** @type { import('mongoose').Model<import('../typings/mongo').Checker, {}>} */
exports.checkerModel = model('checker', checkerSchema, 'checker');

const userSchema = new Schema({
  _id: { type: String, default: uuid },
  name: String,
}, { versionKey: false });

/** @type { import('mongoose').Model<import('../typings/mongo').User, {}>} */
exports.userModel = model('user', userSchema, 'user');

connection.on('disconnected', () => {
  log.app.warn('mongo 断开连接...');
});

connection.on('reconnected', () => {
  log.app.info('mongo 重连成功...');
});

connection.on('error', (error) => {
  log.app.error('mongo 连接异常...', error);
});

connection.on('connected', () => {
  log.app.info('mongo 连接成功...');
});

connect(config.mongodbUrl, { useFindAndModify: false, useNewUrlParser: true, useUnifiedTopology: true });
